import { message } from 'antd';
import axios, { AxiosRequestConfig, AxiosRequestHeaders, Method } from 'axios';
import jsCookie from 'js-cookie';
import { history } from 'umi';

interface IPendingType {
  url?: string;
  methods?: Method;
  params: any;
  data: any;
  cancel: any;
}

interface IBaseResponse<T> {
  code?: number;
  msg?: string;
  data: T;
}

export type ResPromise<D> = Promise<IBaseResponse<D>>;
const baseUrl = '/api';

const service = axios.create({
  baseURL: baseUrl,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'Access-Control-Allow-Origin': '*',
  },
  timeout: 3 * 60 * 1000,
});

// 取消重复请求
const pending: Array<IPendingType> = [];
const CancelToken = axios.CancelToken;

const removePending = (config: AxiosRequestConfig) => {
  pending.forEach((item, index) => {
    if (
      item.url === config.url &&
      item.methods === config.method &&
      JSON.stringify(item.params) === JSON.stringify(config.params) &&
      JSON.stringify(item.data) === JSON.stringify(config.data)
    ) {
      item.cancel('操作太频繁，请稍后再试');
      pending.splice(index, 1);
    }
  });
};

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    removePending(config);

    config.cancelToken = new CancelToken((c) => {
      pending.push({
        url: config.url,
        methods: (config as any).method,
        params: config.params,
        data: config.data,
        cancel: c,
      });
    });

    const headers = config.headers as AxiosRequestHeaders;
    const token = jsCookie.get('token') || '';
    headers['Authorization'] = token;
    config.headers = headers;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  },
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    if (response.status === 200) {
      if (typeof response.data !== 'string' && response.data.code !== 0) {
        message.error(response.data.msg);
        return Promise.reject(response);
      }
      const token = response.headers.authorization;
      if (token) {
        console.log('[ aa ] >');
        jsCookie.set('token', token);
      }

      if (typeof response.data === 'string') {
        const data = JSON.parse(response.data);
        if (data.code !== 0) {
          message.error(data.msg);
          history.replace('/users/login');
          return Promise.reject(response);
        }
      }
      return Promise.resolve(response);
    }
    return Promise.reject(response);
  },
  (error) => {
    const { response } = error;
    if (response) {
      /**
       * 处理401、403等信息
       */

      return Promise.reject(response);
    }

    return Promise.reject();
  },
);

function request<T>(url: string, params: any, method: Method, config?: AxiosRequestConfig): Promise<T> {
  return new Promise((resolve, reject) => {
    let data = {};
    if (method === 'get' || method === 'delete') {
      data = { params };
    }
    if (method === 'post') {
      data = params ? { data: params } : { data: null };
    }

    service({
      url,
      method,
      ...config,
      ...data,
    })
      .then((res) => {
        // 当取消请求时，res里面没有data会导致报错
        if (res?.data) {
          resolve(res?.data);
        }
        if (res?.data === '') {
          resolve(res?.data);
        }
        if (typeof res?.data === 'boolean') {
          resolve(res?.data as unknown as T);
        }
      })
      .catch((error) => {
        reject(error);
      });
  });
}

export function get<T = any>(url: string, params?: any, config?: AxiosRequestConfig) {
  return request<IBaseResponse<T>>(url, params, 'get', config);
}

export function post<T = any>(url: string, params?: any, config?: AxiosRequestConfig) {
  return request<IBaseResponse<T>>(url, params, 'post', config);
}

export function put<T>(url: string, params?: any, config?: AxiosRequestConfig) {
  return request<T>(url, params, 'put', config);
}

export function del<T>(url: string, params?: any, config?: AxiosRequestConfig) {
  return request<T>(url, params, 'delete', config);
}
